home *** CD-ROM | disk | FTP | other *** search
- #ifndef xkernel
- #ifdef BSD
- /* C O P Y R I G H T N O T I C E : */
- /* Copyright 1986 Eric Jul. May not be used for any */
- /* purpose without written permission from the author. */
- /*
- * INTERFACE: Defined by exported procedures.
- *
- * FUNCTION: Provides multiplexing of SIGIO when multiple asynchronous
- * sockets are used.
- *
- * EXPORTS: SISetSockHandler, SIRemoveSockHandler
- *
- * TRACES: SI
- *
- * SNAPSHOTS: None
- *
- *
- * DESIGN: Handlers are set on a per socket basis and
- * are invoked when "select" shows that i/o is possible.
- */
-
- #include <errno.h>
- #include <sys/ioctl.h>
- #include <sys/time.h>
- #include <signal.h>
- #include "Kernel/h/system.h"
- #include "Kernel/h/assert.h"
- #include "Kernel/h/stdTypes.h"
- #include "Kernel/h/sigio.h"
- #include "Kernel/h/kmdTypes.h"
-
- extern void SetHandler();
- extern int errno;
-
- /* Forward */ void SIRemoveSockHandler();
-
- SIHandlerPtr table[3][32];
- static int SIInitialized = 0;
- int mask[3] = { 0, 0, 0};
- int maxSock = 0;
- static struct timeval timeout = {0, 0};
-
- #define DEFAULTSIGIODELAYTIME 50000 /* microseconds */
- int vSIDelayTime = DEFAULTSIGIODELAYTIME;
-
- int SICheck(fSock)
- /* Check for broken sockets */
- {
- int chck[3], nfound;
- while (1) {
- chck[0] = chck[1] = chck[2] = 1 << fSock;
- nfound = select(fSock+1, &chck[0], &chck[1], &chck[2], &timeout);
- if (nfound >= 0) return 1;
- if (errno != EINTR) return 0;
- }
- }
-
- void SIFixBadF()
- /* Clean up Sock structure, generating upcalls for dead sockets */
- {
- int i, j;
- SIHandlerPtr theHandler;
-
- for (j = 0; j <= maxSock; j++)
- for (i = 0; i < 3; i++)
- if (((int) table[i][j]) != 0) {
- if (!SICheck(j)) {
- theHandler = table[SIEXCEPT][j];
- SIRemoveSockHandler(j, SIREAD);
- SIRemoveSockHandler(j, SIWRITE);
- SIRemoveSockHandler(j, SIEXCEPT);
- if (((int)theHandler) != 0) {
- QueueTask(theHandler, (char *) j);
- }
- break;
- }
- }
- }
-
- void SIInterrupt()
- /* Signal handler for SIGIO */
- {
- int nfound, result[3];
- register int i, j;
-
- retry:
- result[0] = mask[0];
- result[1] = mask[1];
- result[2] = 0;
- nfound = select(maxSock+1, &result[0], &result[1], &result[2], &timeout);
- if (nfound == 0) return;
- if (nfound < 0) {
- if (errno == EINTR) goto retry;
- if (errno == EBADF) {
- SIFixBadF();
- goto retry;
- }
- ErrMsg("Bad return from select\n");
- perror("select");
- abort();
- }
- for (i = 0; i < 2; i++)
- for (j = 0; j <= maxSock; j++)
- if (result[i] & (1<<j)) {
- (*table[i][j])(i,j);
- }
- }
-
- void SIEnsureSIGIO()
- /* At times, it is necessary to ensure that a SIGIO happens.
- This procedure ensures this by scheduling a SIGIO event after
- in vSIDelayTime microseconds. */
- {
- (void) MMSetMicroTimer(vSIDelayTime/1000000, vSIDelayTime % 1000000,
- SIInterrupt, NULL, NULL);
- }
-
- void SIInit()
- {
- register i,j;
- KMDSetTrace(SI);
- KMDTrace("SI", 3, "Initializing SIGIO\n");
- for (i=0; i < 3; i++)
- for (j=0; j < 32; j++) table[i][j] = (SIHandlerPtr) NULL;
- SetHandler(SIGIO, SIInterrupt);
- SetHandler(SIGPIPE, SIFixBadF);
- SIInitialized = 1;
- }
-
- void SISetSockHandler(fSock, fKind, fHandler)
- int fSock;
- int fKind;
- SIHandlerPtr fHandler;
- /* Define a handler for a socket. There are three kinds of handlers:
- read: invoked when input is possible on the socket
- write: invoked when output is possible on the socket
- death: invoked when the socket has died and gone away
- (death upcall).
- */
- {
- if (!SIInitialized) SIInit();
- assert(fSock >= 0 && fSock < 32);
- assert(fKind >= SIREAD && fKind <= SIEXCEPT);
- table[fKind][fSock] = fHandler;
- mask[fKind] |= (1 << fSock);
- if (fSock > maxSock) maxSock = fSock;
- }
-
- void SIRemoveSockHandler(fSock, fKind)
- int fSock;
- int fKind;
- /* Remove a handler */
- {
- assert(SIInitialized);
- assert(fSock >= 0 && fSock < 32);
- assert(fKind >= SIREAD && fKind <= SIEXCEPT);
- table[fKind][fSock] = (SIHandlerPtr) NULL;
- mask[fKind] &= ~ (1<<fSock);
- if (fSock >= maxSock) {
- register int i, j, oldMaxSock;
- oldMaxSock = maxSock;
- maxSock = 0;
- for (i=0; i < 2; i++)
- for (j=maxSock; j <= oldMaxSock; j ++)
- if (table[i][j] != (SIHandlerPtr) NULL) maxSock = j;
- }
- }
-
-
- /****************************************************************/
- /* End of SIGIO handling */
- /****************************************************************/
- #endif
- #else
- void SISetSockHandler()
- {}
- void SIRemoveSockHandler()
- {}
- void SIEnsureSIGIO()
- {}
- #endif
-